package fraction;

/**
 * Class Fraction
 *
 * @author lorenz gorse
 */
public class Fraction {
    /**
     * The numerator of the fraction
     */
    protected int numerator;
    
    /**
     * The denominator of the fraction
     */
    protected int denominator;

    /**
     * Creates a new fraction with numerator and denominator (as numerator and denominator ;)
     *
     * @param numerator the numerator
     * @param denominator the denominator
     */
    public Fraction(int numerator, int denominator) {
        int ggt = this.ggT(numerator, denominator);
        this.numerator      = numerator / ggt;
        this.denominator    = denominator / ggt;
    }

    /**
     * Creates a new fraction from a mixed fraction
     *
     * @param f the mixed fraction
     */
    public Fraction(MixedFraction f) {
        int ggt = this.ggT(f.getNumerator(), f.getDenominator());
        this.numerator      = f.getNumerator() / ggt;
        this.denominator    = f.getDenominator() / ggt;
    }

    /**
     * Checks wether f1 and f2 are equal
     *
     * @param f1 the first fraction
     * @param f2 the second fraction
     * @return true if the fractions are equal, otherwise false
     */
    public static boolean isEqual(Fraction f1, Fraction f2) {
        if((f1.getNumerator() == f2.getNumerator()) && (f1.getDenominator() == f2.getDenominator())) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Calculates the product of f1 and f2
     *
     * @param f1 first fraction
     * @param f2 second fraction
     * @return the product of f1 and f2
     */
    public static Fraction multiplicate(Fraction f1, Fraction f2) {
        return new Fraction(
            f1.getNumerator() * f2.getNumerator(),
            f1.getDenominator() * f2.getDenominator()
        );
    }

    /**
     * Calculates the quotient of f1 and f2
     *
     * @param f1 first fraction
     * @param f2 second fraction
     * @return the quotient of f1 and f2
     */
    public static Fraction divide(Fraction f1, Fraction f2) {
        f2 = new Fraction(f2.getDenominator(), f2.getNumerator());
        return Fraction.multiplicate(f1, f2);
    }

    /**
     * Calculates the sum of f1 and f2
     *
     * @param f1 first fraction
     * @param f2 second fraction
     * @return the product of f1 and f2
     */
    public static Fraction add(Fraction f1, Fraction f2) {
        int n = f1.getNumerator() * f2.getDenominator() + f2.getNumerator() * f1.getDenominator();
        int d = f1.getDenominator() * f2.getDenominator();

        return new Fraction(n, d);
    }

    /**
     * Calculates the difference between f1 and f2
     *
     * @param f1 first fraction
     * @param f2 second fraction
     * @return the product of f1 and f2
     */
    public static Fraction subtract(Fraction f1, Fraction f2) {
        int n = f1.getNumerator() * f2.getDenominator() - f2.getNumerator() * f1.getDenominator();
        int d = f1.getDenominator() * f2.getDenominator();

        return new Fraction(n, d);
    }

    /**
     * Concatenates the numerator and denominator to an string that looks like a fraction
     *
     * @return a string that looks like the fraction
     */
    @Override
    public String toString() {
        return this.numerator + "/" + this.denominator;
    }

    /**
     * Calculates the greatest common divisor of a and b
     *
     * @param a first number
     * @param b second number
     * @return the greatest common divisor
     */
    private int ggT(int a, int b) {
        a = Math.abs(a);
        b = Math.abs(b);

        if(a == 0) {
            return b;
        } else {
            while(b != 0) {
                if(a > b) {
                    a = a - b;
                } else {
                    b = b - a;
                }
            }

            return a;
        }
    }

    /**
     * Returns the numerator
     *
     * @return the numerator
     */
    public int getNumerator() {
        return this.numerator;
    }

    /**
     * Returns the denominator
     *
     * @return the denominator
     */
    public int getDenominator() {
        return this.denominator;
    }
}
